package bytecode;

/**
 * 从字节码分析得出的结论：
 * 成员变量的初始化是在构造方法中完成的，有多少个构造方法，初始化指令就会调用几次
 * 静态成员变量同样是在clinit方法完成的，不管有多少个静态变量都是在该方法完成初始化
 */
public class MyTest2 {
    String str = "Welcome";

    private int x = 5;

    public static Integer in = 10;

    public MyTest2(String str) {
        this.str = str;
    }

    public MyTest2(String str, int x) {
        this.str = str;
        this.x = x;
    }

    public MyTest2() {

    }

    public static void main(String[] args) {
        MyTest2 byteCodeTest2 = new MyTest2();
        byteCodeTest2.setX(8);
        in = 20;
    }

    private synchronized void setX(int x) {
        this.x = x;
    }

    public void test(String str) {
        synchronized (this) {//给当前对象上锁
            System.out.println("Hello World");
        }
    }

    //给类字节码码上锁
    public static synchronized void test() {
    }

    static {
        System.out.println();
    }
}

//查看字节码，分析

//javap -verbose -c MyTest2.class
//Classfile /D:/work/jvm_learn/target/classes/bytecode/MyTest2.class
//Last modified 2020-5-2; size 1509 bytes
//        MD5 checksum 389937adc713a61f2bd6bf8f8434c610
//        Compiled from "MyTest2.java"
//public class bytecode.MyTest2
//        minor version: 0
//        major version: 52
//        flags: ACC_PUBLIC, ACC_SUPER
//        Constant pool:
//        #1 = Methodref          #14.#46        // java/lang/Object."<init>":()V
//        #2 = String             #47            // Welcome
//        #3 = Fieldref           #5.#48         // bytecode/MyTest2.str:Ljava/lang/String;
//        #4 = Fieldref           #5.#49         // bytecode/MyTest2.x:I
//        #5 = Class              #50            // bytecode/MyTest2
//        #6 = Methodref          #5.#46         // bytecode/MyTest2."<init>":()V
//        #7 = Methodref          #5.#51         // bytecode/MyTest2.setX:(I)V
//        #8 = Methodref          #52.#53        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
//        #9 = Fieldref           #5.#54         // bytecode/MyTest2.in:Ljava/lang/Integer;
//        #10 = Fieldref           #55.#56        // java/lang/System.out:Ljava/io/PrintStream;
//        #11 = String             #57            // Hello World
//        #12 = Methodref          #58.#59        // java/io/PrintStream.println:(Ljava/lang/String;)V
//        #13 = Methodref          #58.#60        // java/io/PrintStream.println:()V
//        #14 = Class              #61            // java/lang/Object
//        #15 = Utf8               str
//        #16 = Utf8               Ljava/lang/String;
//        #17 = Utf8               x
//        #18 = Utf8               I
//        #19 = Utf8               in
//        #20 = Utf8               Ljava/lang/Integer;
//        #21 = Utf8               <init>
//  #22 = Utf8               (Ljava/lang/String;)V
//          #23 = Utf8               Code
//          #24 = Utf8               LineNumberTable
//          #25 = Utf8               LocalVariableTable
//          #26 = Utf8               this
//          #27 = Utf8               Lbytecode/MyTest2;
//          #28 = Utf8               (Ljava/lang/String;I)V
//          #29 = Utf8               ()V
//          #30 = Utf8               main
//          #31 = Utf8               ([Ljava/lang/String;)V
//          #32 = Utf8               args
//          #33 = Utf8               [Ljava/lang/String;
//          #34 = Utf8               byteCodeTest2
//          #35 = Utf8               setX
//          #36 = Utf8               (I)V
//          #37 = Utf8               test
//          #38 = Utf8               StackMapTable
//          #39 = Class              #50            // bytecode/MyTest2
//          #40 = Class              #62            // java/lang/String
//          #41 = Class              #61            // java/lang/Object
//          #42 = Class              #63            // java/lang/Throwable
//          #43 = Utf8               <clinit>
//  #44 = Utf8               SourceFile
//          #45 = Utf8               MyTest2.java
//          #46 = NameAndType        #21:#29        // "<init>":()V
//          #47 = Utf8               Welcome
//          #48 = NameAndType        #15:#16        // str:Ljava/lang/String;
//          #49 = NameAndType        #17:#18        // x:I
//          #50 = Utf8               bytecode/MyTest2
//          #51 = NameAndType        #35:#36        // setX:(I)V
//          #52 = Class              #64            // java/lang/Integer
//          #53 = NameAndType        #65:#66        // valueOf:(I)Ljava/lang/Integer;
//          #54 = NameAndType        #19:#20        // in:Ljava/lang/Integer;
//          #55 = Class              #67            // java/lang/System
//          #56 = NameAndType        #68:#69        // out:Ljava/io/PrintStream;
//          #57 = Utf8               Hello World
//          #58 = Class              #70            // java/io/PrintStream
//          #59 = NameAndType        #71:#22        // println:(Ljava/lang/String;)V
//          #60 = NameAndType        #71:#29        // println:()V
//          #61 = Utf8               java/lang/Object
//          #62 = Utf8               java/lang/String
//          #63 = Utf8               java/lang/Throwable
//          #64 = Utf8               java/lang/Integer
//          #65 = Utf8               valueOf
//          #66 = Utf8               (I)Ljava/lang/Integer;
//          #67 = Utf8               java/lang/System
//          #68 = Utf8               out
//          #69 = Utf8               Ljava/io/PrintStream;
//          #70 = Utf8               java/io/PrintStream
//          #71 = Utf8               println
//          {
//          java.lang.String str;
//          descriptor: Ljava/lang/String;
//          flags:
//
//public static java.lang.Integer in;
//        descriptor: Ljava/lang/Integer;
//        flags: ACC_PUBLIC, ACC_STATIC
//
//public bytecode.MyTest2(java.lang.String);
//        descriptor: (Ljava/lang/String;)V
//        flags: ACC_PUBLIC
//        Code:
//        stack=2, locals=2, args_size=2
//        0: aload_0
//        1: invokespecial #1                  // Method java/lang/Object."<init>":()V
//        4: aload_0
//        5: ldc           #2                  // String Welcome
//        7: putfield      #3                  // Field str:Ljava/lang/String;
//        10: aload_0
//        11: iconst_5
//        12: putfield      #4                  // Field x:I
//        15: aload_0
//        16: aload_1
//        17: putfield      #3                  // Field str:Ljava/lang/String;
//        20: return
//        LineNumberTable:
//        line 10: 0
//        line 4: 4
//        line 6: 10
//        line 11: 15
//        line 12: 20
//        LocalVariableTable:
//        Start  Length  Slot  Name   Signature
//        0      21     0  this   Lbytecode/MyTest2;
//        0      21     1   str   Ljava/lang/String;
//
//public bytecode.MyTest2(java.lang.String, int);
//        descriptor: (Ljava/lang/String;I)V
//        flags: ACC_PUBLIC
//        Code:
//        stack=2, locals=3, args_size=3
//        0: aload_0
//        1: invokespecial #1                  // Method java/lang/Object."<init>":()V
//        4: aload_0
//        5: ldc           #2                  // String Welcome
//        7: putfield      #3                  // Field str:Ljava/lang/String;
//        10: aload_0
//        11: iconst_5
//        12: putfield      #4                  // Field x:I
//        15: aload_0
//        16: aload_1
//        17: putfield      #3                  // Field str:Ljava/lang/String;
//        20: aload_0
//        21: iload_2
//        22: putfield      #4                  // Field x:I
//        25: return
//        LineNumberTable:
//        line 14: 0
//        line 4: 4
//        line 6: 10
//        line 15: 15
//        line 16: 20
//        line 17: 25
//        LocalVariableTable:
//        Start  Length  Slot  Name   Signature
//        0      26     0  this   Lbytecode/MyTest2;
//        0      26     1   str   Ljava/lang/String;
//        0      26     2     x   I
//
//public bytecode.MyTest2();
//        descriptor: ()V
//        flags: ACC_PUBLIC
//        Code:
//        stack=2, locals=1, args_size=1
//        0: aload_0
//        1: invokespecial #1                  // Method java/lang/Object."<init>":()V
//        4: aload_0
//        5: ldc           #2                  // String Welcome
//        7: putfield      #3                  // Field str:Ljava/lang/String;
//        10: aload_0
//        11: iconst_5
//        12: putfield      #4                  // Field x:I
//        15: return
//        LineNumberTable:
//        line 19: 0
//        line 4: 4
//        line 6: 10
//        line 21: 15
//        LocalVariableTable:
//        Start  Length  Slot  Name   Signature
//        0      16     0  this   Lbytecode/MyTest2;
//
//public static void main(java.lang.String[]);
//        descriptor: ([Ljava/lang/String;)V
//        flags: ACC_PUBLIC, ACC_STATIC
//        Code:
//        stack=2, locals=2, args_size=1
//        0: new           #5                  // class bytecode/MyTest2
//        3: dup
//        4: invokespecial #6                  // Method "<init>":()V
//        7: astore_1
//        8: aload_1
//        9: bipush        8
//        11: invokespecial #7                  // Method setX:(I)V
//        14: bipush        20
//        16: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
//        19: putstatic     #9                  // Field in:Ljava/lang/Integer;
//        22: return
//        LineNumberTable:
//        line 24: 0
//        line 25: 8
//        line 26: 14
//        line 27: 22
//        LocalVariableTable:
//        Start  Length  Slot  Name   Signature
//        0      23     0  args   [Ljava/lang/String;
//        8      15     1 byteCodeTest2   Lbytecode/MyTest2;
//
//public void test(java.lang.String);
//        descriptor: (Ljava/lang/String;)V
//        flags: ACC_PUBLIC
//        Code:
//        stack=2, locals=4, args_size=2
//        0: aload_0
//        1: dup
//        2: astore_2
//        3: monitorenter
//        4: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
//        7: ldc           #11                 // String Hello World
//        9: invokevirtual #12                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
//        12: aload_2
//        13: monitorexit
//        14: goto          22
//        17: astore_3
//        18: aload_2
//        19: monitorexit
//        20: aload_3
//        21: athrow
//        22: return
//        Exception table:
//        from    to  target type
//        4    14    17   any
//        17    20    17   any
//        LineNumberTable:
//        line 34: 0
//        line 35: 4
//        line 36: 12
//        line 37: 22
//        LocalVariableTable:
//        Start  Length  Slot  Name   Signature
//        0      23     0  this   Lbytecode/MyTest2;
//        0      23     1   str   Ljava/lang/String;
//        StackMapTable: number_of_entries = 2
//        frame_type = 255 /* full_frame */
//        offset_delta = 17
//        locals = [ class bytecode/MyTest2, class java/lang/String, class java/lang/Object ]
//        stack = [ class java/lang/Throwable ]
//        frame_type = 250 /* chop */
//        offset_delta = 4
//
//public static synchronized void test();
//        descriptor: ()V
//        flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
//        Code:
//        stack=0, locals=0, args_size=0
//        0: return
//        LineNumberTable:
//        line 41: 0
//
//static {};
//        descriptor: ()V
//        flags: ACC_STATIC
//        Code:
//        stack=1, locals=0, args_size=0
//        0: bipush        10
//        2: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
//        5: putstatic     #9                  // Field in:Ljava/lang/Integer;
//        8: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
//        11: invokevirtual #13                 // Method java/io/PrintStream.println:()V
//        14: return
//        LineNumberTable:
//        line 8: 0
//        line 44: 8
//        line 45: 14
//        }
//        SourceFile: "MyTest2.java"
